﻿using Colorful.API;
using Colorful.Database;
using Colorful.Image;
using HtmlAgilityPack;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WebMarkupMin.Core;

namespace Colorful.CMS.Core
{
    [Route("cms")]
    public class NodeController : BaseAPI
    {
        private const string ARTICLE_UPLOAD_PATH = "/upFiles/article";
        private const string ARTICLE_GET_ERROR = "文章获取失败，请稍候重试！若问题重复出现请联系开发人员解决！";

        #region 获取微信文章
        [Route("article/weixin")]
        public async Task<IActionResult> GetWeXinArticle(string url, string appkey, string action)
        {
            try
            {
                using (var db = CMSDbHelper.GetDb())
                {
                    if (string.IsNullOrEmpty(url))
                    {
                        return this.GetResult(false, "参数Url不能为空！");
                    }
                    var article = GetArticle(url, db);
                    if (!string.IsNullOrEmpty(article.Content))
                        return this.GetResult(true, article);
                    var content = await HttpHelper.GetContent(url);
                    //var web = new HtmlWeb();
                    //var doc = await web.LoadFromWebAsync(url);
                    //var content = doc.ParsedText;

                    #region 匹配标题
                    var titleMatch = Regex.Match(content, @"<h[1-9]{1,1}[\S ]*?title[\S ]*?>([\s\S]*?)</h[1-9]{1,1}>");
                    if (titleMatch.Success)
                    {
                        article.Title = titleMatch.Groups[1].Value.Trim();
                    }
                    #endregion

                    #region 匹配作者
                    {
                        var match = Regex.Match(content, "<em class=\"rich_media_meta rich_media_meta_text\">([\\S ]+)</em>");
                        if (match.Success)
                            article.Author = match.Groups[1].Value.Trim();
                    }
                    #endregion

                    #region 匹配来源
                    {
                        var match = Regex.Match(content, "<a[\\S ]+id=\"post-user\">([\\S ]+)</a>");
                        if (match.Success)
                            article.Source = match.Groups[1].Value.Trim();
                    }
                    #endregion

                    #region 匹配发布时间
                    {
                        var match = Regex.Match(content, "<em[\\S ]+\"post-date\"[\\S ]+>([0-9]{4,4}-[0-9]{2,2}-[0-9]{2,2})</em>");
                        if (match.Success)
                        {
                            DateTime date;
                            DateTime.TryParse(match.Groups[1].Value.Trim(), out date);
                            article.Date = date;
                        }
                    }
                    #endregion

                    #region 匹配正文
                    {
                        var match = Regex.Match(content, "<div[^>]*?id=\"js_content\">[\\s\\S]*?</div>", RegexOptions.IgnoreCase);
                        if (match.Success)
                        {
                            var rnd = CommonHelper.GetRandom();
                            var savePath = $"{ARTICLE_UPLOAD_PATH}/{appkey}/weixin/{DateTime.Now.ToString("yyyyMMdd")}";
                            var articleContent = match.Value;

                            var imageList = new List<string>();
                            #region 处理背景图片
                            var backgroundMatches = Regex.Matches(articleContent, @"background-image[^h]*?(http[\s\S]*?wx_fmt=(?:jpeg|png|gif|jpg))");
                            if (backgroundMatches.Count > 0)
                            {
                                foreach (Match bMatch in backgroundMatches)
                                {
                                    var imgUrl = bMatch.Groups[1].Value;
                                    if (imageList.Contains(imgUrl))
                                        continue;
                                    imageList.Add(imgUrl);
                                }
                            }
                            #endregion

                            #region 处理图片
                            var imgMatches = Regex.Matches(articleContent, "<img[^>]*?data-src=[\"'](http[s]?://[^\"|']+)[\"'][^>]*?>", RegexOptions.IgnoreCase); //src=[\"'](http[s]?://[^\"|']+)[\"'][^>]*?
                            if (imgMatches.Count > 0)
                            {
                                foreach (Match imgMatch in imgMatches)
                                {
                                    var imgUrl = imgMatch.Groups[1].Value;
                                    if (imageList.Contains(imgUrl))
                                        continue;
                                    imageList.Add(imgUrl);
                                }
                            }
                            #endregion

                            #region 下载图片
                            if (imageList.Count > 0)
                            {
                                articleContent = DownloadImages(articleContent, imageList, savePath);
                            }
                            #endregion

                            #region 处理Iframe
                            var iframeMatches = Regex.Matches(articleContent, "<iframe[^>]*?data-src=\"(http[^\"]*?)\"", RegexOptions.IgnoreCase);
                            if (iframeMatches.Count > 0)
                            {
                                foreach (Match iframeMatch in iframeMatches)
                                {
                                    articleContent = articleContent.Replace($"data-src=\"{iframeMatch.Groups[1].Value}\"", $"src=\"{iframeMatch.Groups[1].Value}\"");
                                }
                            }
                            #endregion

                            content = articleContent;

                            #region 保存文章数据
                            article.Content = content;
                            article.AddDate = DateTime.Now;
                            FilterArticle(article);
                            db.ArticleCaches.Add(article);
                            #endregion

                            return this.GetResult(true, article);
                        }
                    }
                    #endregion

                    if (!string.IsNullOrEmpty(article.Title))
                        return this.GetResult(true, article);
                    return this.GetResult(false, ARTICLE_GET_ERROR);
                }
            }
            catch (TaskCanceledException)
            {
                return this.GetResult(false, "网页加载超时，请稍候重试！");
            }
            catch (Exception ex)
            {
                return this.GetResult(ex, true);
            }
        }
        #endregion

        #region 从网页读取文章
        [Route("article/web")]
        public async Task<IActionResult> GetWebArticle(string url)
        {
            try
            {
                using (var db = CMSDbHelper.GetDb())
                {
                    if (string.IsNullOrEmpty(url))
                    {
                        return this.GetResult(false, "参数Url不能为空！");
                    }
                    var article = GetArticle(url, db);
                    if (!string.IsNullOrEmpty(article.Content))
                        return this.GetResult(true, article);
                    url = $"{MyWebService.PythonAPIUrl}api/article?url={url.UrlEncode()}";
                    var content = await HttpHelper.GetContent(url);

                    if (!string.IsNullOrEmpty(content))
                    {
                        var jsonResult = JsonHelper.Parse<Models.JsonResult>(content);
                        article.Title = jsonResult.data["Title"];
                        article.Content = jsonResult.data["Content"];
                        article.Author = jsonResult.data["Author"];
                        article.Source = jsonResult.data["Source"];
                        article.Summary = jsonResult.data["Summary"];
                        article.Keyword = jsonResult.data["Keyword"];
                        FilterArticle(article);
                        db.ArticleCaches.Add(article);
                        return this.GetResult(true, article);
                    }
                    return this.GetResult(false, ARTICLE_GET_ERROR);
                }
            }
            catch (Exception ex)
            {
                return this.GetResult(ex);
            }
        }
        #endregion

        #region 根据Url获取文章
        private Models.ArticleCache GetArticle(string url, DbContext db)
        {
            #region 检查文章缓存
            var id = url.GetHash();
            var article = db.ArticleCaches.FirstOrDefault(a => a.Id == id);
            if (article != null)
                return article;
            article = new Models.ArticleCache()
            {
                Id = id,
                Url = url,
            };
            #endregion
            return article;
        }
        #endregion

        #region 过滤文章内容 FilterArticle
        private Models.ArticleCache FilterArticle(Models.ArticleCache article)
        {
            #region 压缩Html
            var htmlMinifier = new HtmlMinifier(new HtmlMinificationSettings()
            {
                AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes
            });
            var result = htmlMinifier.Minify(article.Content);
            if (result.Errors.Count == 0)
                article.Content = result.MinifiedContent;
            #endregion
            return article;
        }
        #endregion

        #region 下载图片
        private string DownloadImages(string content, List<string> imageList, string savePath)
        {
            using (var httpClient = new MyHttpClient())
            {
                foreach (var imgUrl in imageList)
                {
                    var isGif = imgUrl.EndsWith("gif", StringComparison.OrdinalIgnoreCase);
                    if (isGif)
                    {
                        Console.WriteLine(imgUrl);
                    }
                    var localImgUrl = $"{savePath}/{WebService.GetUniqueId()}.{(isGif ? "gif" : "jpg")}";
                    FormHelper.CreateDirectory(HttpContext.MapPath(savePath));
                    var filePath = HttpContext.MapPath(localImgUrl);
                    using (var stream = httpClient.GetStreamAsync(imgUrl).Result)
                    {
                        var newPath = filePath;
                        newPath = new ColorImage(newPath).Compress(stream, new System.Drawing.Size(1000, 1000)).SavePath;
                        if (newPath != filePath)
                            localImgUrl = localImgUrl.Replace(".jpg", ".png");
                        localImgUrl = $"{WebService.CMSAPIUrl}{localImgUrl.Substring(1)}";
                        content = content.Replace(imgUrl, localImgUrl);
                        content = content.Replace($"data-src=\"{localImgUrl}\"", $"src=\"{localImgUrl}\"");
                    }
                }
            }
            return content;
        }
        #endregion
    }
}
